/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.mzk.oai.metadataRepository.repository.depricatedItem;

import cz.mzk.oai.metadataRepository.repository.depricatedItem.ItemsManager;
import cz.mzk.oai.metadataRepository.repository.depricatedItem.Item;
import cz.mzk.oai.metadataRepository.metadata.MetadataFormat;
import cz.mzk.oai.metadataRepository.repository.Identifier;
import cz.mzk.oai.metadataRepository.repository.collections.MetadataCollection;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 *
 * @author Martin Rehanek (rehan at mzk.cz)
 */
public class PropertiesBasedItemsManager implements ItemsManager {

    private static String PROPERTIES_FILE_NAME = "collection.properties";
    //private Map<String, Item> items = new HashMap<String, Item>();
    private Map<Identifier, Item> items = new HashMap<Identifier, Item>();
    private File propertiesFile;
    //TODO: pozor na to, ze si drzi instanci MetadataCollection
    private final MetadataCollection collection;

    public PropertiesBasedItemsManager(MetadataCollection collection) throws IOException {
        this.collection = collection;
        buildPropertiesFile(collection.getRootDir());
        createIfNotExists(propertiesFile);
        loadItems();
    }

    private void buildPropertiesFile(File dirWithPropertiesFile) throws IOException {
        String filename = dirWithPropertiesFile + File.separator + PROPERTIES_FILE_NAME;
        propertiesFile = new File(filename);
    }

    private void createIfNotExists(File file) throws IOException {
        if (!file.exists()) {
            file.createNewFile();
        }
    }

    private void loadItems() throws IOException {
        Properties properties = loadPropertiesFromFile(propertiesFile);
        loadItemsFromProperties(properties);
    }

    private Properties loadPropertiesFromFile(File propertiesFile) throws IOException {
        Properties properties = new Properties();
        properties.load(new FileInputStream(propertiesFile));
        return properties;
    }

    /**
     * Loads items from the properties
     */
    private void loadItemsFromProperties(Properties properties) {
        Set<Object> keys = properties.keySet();
        for (Object key : keys) {
            String idString = (String) key;
            Identifier id = extractIdentifier(idString);
            String propertyValue = properties.getProperty(idString);
            Item item = new Item(id, collection, propertyValue);
            items.put(id, item);
        }
    }

    private Identifier extractIdentifier(String encodedIdString) {
        //TODO: vytahnout bazi a sysno z encodedString a vytvorit instanci Identifier
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Should be called after finished working with collection
     */
    public void persistItems() throws IOException {
        Properties properties = itemsToProperties();
        savePropertiesToFile(properties);
    }

    private Properties itemsToProperties() {
        Properties properties = new Properties();
        for (Item item : items.values()) {
            //System.out.println("prop: " + item.toProperty());
            properties.setProperty(item.getId(), item.toProperty());
        }
        return properties;
    }

    private void savePropertiesToFile(Properties properties) throws IOException {
        properties.store(new FileOutputStream(propertiesFile), null);
    }

    public Item removeItem(Identifier id) {
        Item removedItem = items.remove(id);
        if (removedItem == null) {
            throw new IllegalArgumentException("No item with id " + id.toString() + " in collection " + collection.getName());
        } else {
            return removedItem;
        }
    }

    public boolean containsItem(Identifier id) {
        return items.containsKey(id);
    }

    public Item getItem(Identifier id) {
        return items.get(id);
    }

    public Item createItem(Identifier id) {
        Item item = new Item(id, collection);
        items.put(id, item);
        return item;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        //System.out.println("items: " + items.size());
        int marcRecords = 0;
        int eseRecords = 0;
        for (Item item : items.values()) {
            marcRecords += item.hasRecord(MetadataFormat.marc21) ? 1 : 0;
            eseRecords += item.hasRecord(MetadataFormat.ese) ? 1 : 0;
        }

        builder.append("items: ");
        builder.append(items.size());
        builder.append('\n');

        builder.append("marc records : ");
        builder.append(marcRecords);
        builder.append('\n');

        builder.append("ese records: ");
        builder.append(eseRecords);
        builder.append('\n');
        return builder.toString();
    }

    public int size() {
        return items.size();
    }

    public Iterable<Item> getAllItems() {
        return items.values();
    }

    public List<Item> getItems(MetadataFormat metadataFormat) {
        List<Item> ids = new ArrayList<Item>();
        for (Item item : items.values()) {
            if (item.hasRecord(metadataFormat)) {
                ids.add(item);
            }
        }
        return ids;
    }

    public void updateItem(Item item){
        Item itemfound = items.get(item.getIdentifier());
        if (itemfound == null) {
            throw new IllegalArgumentException("No such item found");
        }
        items.put(item.getIdentifier(), item);
    }
}
